﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Xml.Serialization;

namespace BugLister
{
    public class BugCollection : IList<BugEntry>, INotifyCollectionChanged
    {
        public event NotifyCollectionChangedEventHandler CollectionChanged;

        private BugEntry.BugImportance?  _impoFilter;
        private BugEntry.BugType?        _typeFilter;
        private bool?                    _fixedFilter;

        private List<BugEntry> _items;
        private List<BugEntry> _displayItems
        {
            get
            {
                return _items.Where(b => IsFilterd(b)).ToList();
            }
        }
        public BugCollection()
        {
            _items = new List<BugEntry>();
        }

        private bool IsFilterd(BugEntry item)
        {
            return  (_typeFilter ?? item.Type) == item.Type &&
                    (_impoFilter ?? item.Importance) == item.Importance &&
                    (_fixedFilter ?? item.Fixed) == item.Fixed;
        }

        public void Update()
        {   
            if(CollectionChanged != null)
                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        public void Filter(BugEntry.BugImportance? bugImportance)
        {
            Filter(bugImportance, _typeFilter, _fixedFilter);
        }
        public void Filter(BugEntry.BugType? bugType)
        {
            Filter(_impoFilter, bugType, _fixedFilter);
        }
        public void Filter(bool? isFixed)
        {
            Filter(_impoFilter, _typeFilter, isFixed);
        }
        public void Filter(BugEntry.BugImportance? bugImportance, BugEntry.BugType? bugType, bool? @fixed)
        {
            _impoFilter = bugImportance;
            _typeFilter = bugType;
            _fixedFilter = @fixed;
            Update();
        }
        public void ResetFilters()
        {
            _fixedFilter = null;
            _typeFilter = null;
            _impoFilter = null;
        }

        public void Add(BugEntry item)
        {
            _items.Add(item);
            Update();
        }
        public void Add(object item)
        {
            var bug = item as BugEntry;
            if (bug == null)
                return;
            Add(bug);
            Update();
        }
        public void Clear()
        {
            _items.Clear();
            Update();
        }

        public bool Contains(BugEntry item)
        {
            return _displayItems.Contains(item);
        }

        public void CopyTo(BugEntry[] array, int arrayIndex)
        {
            _displayItems.CopyTo(array, arrayIndex);
        }

        public bool Remove(BugEntry item)
        {
            if (!_items.Contains(item))
                return false;
            _items.Remove(item);
            Update();
            return true;
        }

        public int Count
        {
            get
            {
                return _displayItems.Count;
            }
        }

        public bool IsReadOnly
        {
            get
            {
                return false;
            }
        }

        public IEnumerator GetEnumerator()
        {
            return _displayItems.GetEnumerator();
        }

        IEnumerator<BugEntry> IEnumerable<BugEntry>.GetEnumerator()
        {
            return _displayItems.GetEnumerator();
        }

        public int IndexOf(BugEntry item)
        {
            return _displayItems.IndexOf(item);
        }

        public void Insert(int index, BugEntry item)
        {
            _items.Add(item);
            Update();
        }

        public void RemoveAt(int index)
        {
            _items.Remove(_displayItems[index]);
            Update();
        }

        public BugEntry this[int index]
        {
            get
            {
                // TODO: Implement this indexer getter
                return _displayItems[index];
            }
            set
            {
                // TODO: Implement this indexer setter
                _items[_items.IndexOf(_displayItems[index])] = value;
            }
        }
        public static BugCollection LoadBugs(string fileName)
        {
            XmlSerializer xmlSerial = new XmlSerializer(typeof(List<BugEntry>));
            var bugs = xmlSerial.Deserialize(File.OpenRead(fileName));
            var bugList = (List<BugEntry>)bugs;
            return new BugCollection { _items = bugList };
        }
        public static void SaveBugs(string fileName, BugCollection bugs)
        {
            XmlSerializer xmlSerial = new XmlSerializer(typeof(List<BugEntry>));

            xmlSerial.Serialize(File.Create(fileName), bugs._items);
        }
    }
    
}